﻿using System;
using System.Activities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Reactor.ServiceGrid.Authoring;
using Reactor.ServiceGrid.Packages;
using ServicePackage.Console.Resources;

namespace ServicePackage.Console.Activities
{
    public class CreatePackage : CodeActivity<string>
    {
        private static readonly HashSet<string> Exclude = new HashSet<string>(new[] { Constants.PackageExtension, Constants.ManifestExtension }, StringComparer.OrdinalIgnoreCase);

        public InArgument<string> SpecFilePath { get; set; }
        public InArgument<bool> Verbose { get; set; }

        #region Overrides of CodeActivity<string>

        /// <summary>
        /// When implemented in a derived class, performs the execution of the activity.
        /// </summary>
        /// <returns>
        /// The result of the activity’s execution.
        /// </returns>
        /// <param name="context">The execution context under which the activity executes.</param>
        protected override string Execute(CodeActivityContext context)
        {
            var specFile = SpecFilePath.Get(context);
            System.Console.WriteLine(ConsoleResources.PackageCommandAttemptingToBuildPackage, Path.GetFileName(specFile));

            var builder = new PackageBuilder(specFile, Path.GetDirectoryName(specFile));

            var outputPath = String.Join(".", builder.Id, builder.Version, Constants.PackageExtension.TrimStart('.'));

            // Remove the output file or the package spec might try to include it (which is default behavior)
            builder.Files.RemoveAll(file => Exclude.Contains(Path.GetExtension(file.Path)));

            outputPath = Path.Combine(Directory.GetCurrentDirectory(), outputPath);

            try
            {
                using (Stream stream = File.Create(outputPath))
                {
                    builder.Save(stream);
                }
            }
            catch
            {
                if (File.Exists(outputPath)) File.Delete(outputPath);
                throw;
            }

            if (Verbose.Get(context))
            {
                System.Console.WriteLine();

                var package = new ZipPackage(outputPath);
                foreach (var file in package.GetFiles().OrderBy(p => p.Path.Length))
                {
                    System.Console.WriteLine(ConsoleResources.PackageCommandAddedFile, file.Path);
                }
                System.Console.WriteLine();
            }

            System.Console.WriteLine(ConsoleResources.PackageCommandSuccess, outputPath);

            return outputPath;
        }

        #endregion
    }
}
